﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PerCederberg.Grammatica.Runtime;

namespace SafeScript.MetaModel.Statements
{
    public class ReturnStatement : Statement
    {
        public Operator Operator;
        /// <summary>
        /// MemberFunction, Constructor, Getter or Setter in which the return statement occurs.
        /// </summary>
        public object Context;

        public override void ComputeType(ErrorReport report)
        {
            ITypeDef goal = null;
            if (this.Context is MemberFunction)
                goal = (this.Context as MemberFunction).ReturnType;
            else if (this.Context is FunctionOperator)
                goal = (this.Context as FunctionOperator).ReturnType;
            else if (this.Context is PropertyGetter)
                goal = (this.Context as PropertyGetter).Property.Type;
            else if (this.Context is PropertySetter)
                goal = VoidType.Self;
            else
                System.Diagnostics.Debug.Assert(false, "Unknown context for the return statement");

            if ((goal is VoidType && this.Operator != null) || ( !(goal is VoidType) && this.Operator == null))
            {
                report.Add(new ErrorEntry(this.Node) { Type = ErrorType.ReturnTypeMismatch });
                return;
            }
            if (goal is VoidType)
                return;

            ITypeDef t = this.Operator.ComputeType(goal, false, report);
            if (t == null)
                return;
            InstanceType it = this.ToInstance(ref this.Operator, t, report);
            if (it == null)
                return;

            if (!it.CanBeAssignedTo(goal))
                report.Add(new ErrorEntry(this.Node) { Type = ErrorType.ReturnTypeMismatch });
        }
    }
}
